#define BLINKER_WIFI
#define BLINKER_MIOT_OUTLET

#define BLINKER_DUEROS_OUTLET

#define BLINKER_ALIGENIE_OUTLET

//#define BLINKER_WITHOUT_SSL

#include <Servo.h> 
#include <Blinker.h>
#include <WiFiUDP.h>
#include <ESP8266Ping.h>

char auth[] = "35a74dc36a92";
char ssid[] = "Sweet_meng";
char pswd[] = "aita0116.";

BlinkerButton Button1("k1");
BlinkerSlider Slider1("ser-num");   //实时位置 滑块 数据键名  范围1-180

Servo myservo;
int ser_num;
//唤醒目标电脑的mac地址
byte mac[] = {0x00, 0xE0, 0x70, 0x49, 0x1D, 0xE7};
byte preamble[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
//幻数据包需要在局域网中广播发送,要控制的电脑的网段的255地址
IPAddress ip(192, 168, 0, 255);
//建立一个WiFiUDP对象 UDP
WiFiUDP UDP;
//UDP接收地址，我这里是使用的广播，注意网段
const char *UDPAddress = "192.168.0.108";
//UDP端口
const int UDPPort = 7101;
bool oState = false;

void heartbeat()
{
    BLINKER_LOG("heartbeat,state: ", oState);
    if (HIGH == oState)
    {
        Button1.print("on");
    }
    else
    {
        Button1.print("off");
    }
}

void button1_callback(const String &state)
{
    BLINKER_LOG("get button state: ", state);
    if (state == BLINKER_CMD_ON)
    {
        BLINKER_LOG("Toggle on!");
        UDP.beginPacket(ip, 9);               //UDP发送到目标（IP，端口）
        UDP.write(preamble, sizeof preamble); //写入包头(FF,FF,FF,FF,FF,FF)
        for (byte i = 0; i < 16; i++)
        {
            UDP.write(mac, sizeof mac);
        }
        BLINKER_LOG("唤醒主机");
        UDP.endPacket();
        Button1.print("on");
        oState = true;
    }
    else if (state == BLINKER_CMD_OFF)
    {
        BLINKER_LOG("Toggle off!");
        char sd[] = "shut";                   //与电脑相对应的指令
        UDP.beginPacket(UDPAddress, UDPPort); //准备发送，设置地址和端口
        UDP.write((char *)sd, 8);
        BLINKER_LOG("关闭主机");
        UDP.endPacket();
        Button1.print("off");
        oState = false;
    }
    BlinkerMIOT.powerState(oState ? "on" : "off");
    BlinkerMIOT.print();

    BlinkerDuerOS.powerState(oState ? "on" : "off");
    BlinkerDuerOS.print();

    BlinkerAliGenie.powerState(oState ? "on" : "off");
    BlinkerAliGenie.print();
}

void slider1_callback(int32_t value)
{
    ser_num = value;
    myservo.write(ser_num);
    Blinker.delay(500);
    BLINKER_LOG("get slider value: ", value);
}

void miotPowerState(const String &state)
{
    BLINKER_LOG("need set power state: ", state);
    if (state == BLINKER_CMD_ON)
    {
        UDP.beginPacket(ip, 9);               //UDP发送到目标（IP，端口）
        UDP.write(preamble, sizeof preamble); //写入包头(FF,FF,FF,FF,FF,FF)
        for (byte i = 0; i < 16; i++)
        {
            UDP.write(mac, sizeof mac);
        }
        BLINKER_LOG("唤醒主机");
        UDP.endPacket();
        oState = true;
    }
    else if (state == BLINKER_CMD_OFF)
    {
        char sd[] = "shut";                   //与电脑相对应的指令
        UDP.beginPacket(UDPAddress, UDPPort); //准备发送，设置地址和端口
        UDP.write((char *)sd, 8);
        BLINKER_LOG("关闭主机");
        UDP.endPacket();
        oState = false;
    }
    BlinkerMIOT.powerState(oState ? "on" : "off");
    BlinkerMIOT.print();
}

void miotQuery(int32_t queryCode)
{
    BLINKER_LOG("MIOT Query codes: ", queryCode);
    switch (queryCode)
    {
    case BLINKER_CMD_QUERY_ALL_NUMBER:
        BLINKER_LOG("MIOT Query All");
        BlinkerMIOT.powerState(oState ? "on" : "off");
        BlinkerMIOT.print();
        break;
    case BLINKER_CMD_QUERY_POWERSTATE_NUMBER:
        BLINKER_LOG("MIOT Query Power State");
        BlinkerMIOT.powerState(oState ? "on" : "off");
        BlinkerMIOT.print();
        break;
    default:
        BlinkerMIOT.powerState(oState ? "on" : "off");
        BlinkerMIOT.print();
        break;
    }
}

void duerPowerState(const String &state)
{
    BLINKER_LOG("need set power state: ", state);
    if (state == BLINKER_CMD_ON)
    {
        UDP.beginPacket(ip, 9);               //UDP发送到目标（IP，端口）
        UDP.write(preamble, sizeof preamble); //写入包头(FF,FF,FF,FF,FF,FF)
        for (byte i = 0; i < 16; i++)
        {
            UDP.write(mac, sizeof mac);
        }
        BLINKER_LOG("唤醒主机");
        UDP.endPacket();
        oState = true;
    }
    else if (state == BLINKER_CMD_OFF)
    {
        char sd[] = "shut";                   //与电脑相对应的指令
        UDP.beginPacket(UDPAddress, UDPPort); //准备发送，设置地址和端口
        UDP.write((char *)sd, 8);
        BLINKER_LOG("关闭主机");
        UDP.endPacket();
        oState = false;
    }
    BlinkerDuerOS.powerState(oState ? "on" : "off");
    BlinkerDuerOS.print();
}

void duerQuery(int32_t queryCode)
{
    BLINKER_LOG("DuerOS Query codes: ", queryCode);
    switch (queryCode)
    {
    case BLINKER_CMD_QUERY_ALL_NUMBER:
        BLINKER_LOG("DuerOS Query All");
        BlinkerDuerOS.powerState(oState ? "on" : "off");
        BlinkerDuerOS.time(millis());
        BlinkerDuerOS.print();
        break;
    case BLINKER_CMD_QUERY_POWERSTATE_NUMBER:
        BLINKER_LOG("DuerOS Query Power State");
        BlinkerDuerOS.powerState(oState ? "on" : "off");
        BlinkerDuerOS.print();
        break;
    case BLINKER_CMD_QUERY_TIME_NUMBER:
        BLINKER_LOG("DuerOS Query time");
        BlinkerDuerOS.time(millis());
        BlinkerDuerOS.print();
        break;
    default:
        BlinkerDuerOS.powerState(oState ? "on" : "off");
        BlinkerDuerOS.time(millis());
        BlinkerDuerOS.print();
        break;
    }
}

void aligeniePowerState(const String &state)
{
    BLINKER_LOG("need set power state: ", state);
    if (state == BLINKER_CMD_ON)
    {
        UDP.beginPacket(ip, 9);               //UDP发送到目标（IP，端口）
        UDP.write(preamble, sizeof preamble); //写入包头(FF,FF,FF,FF,FF,FF)
        for (byte i = 0; i < 16; i++)
        {
            UDP.write(mac, sizeof mac);
        }
        BLINKER_LOG("唤醒主机");
        UDP.endPacket();
        oState = true;
    }
    else if (state == BLINKER_CMD_OFF)
    {
        char sd[] = "shut";                   //与电脑相对应的指令
        UDP.beginPacket(UDPAddress, UDPPort); //准备发送，设置地址和端口
        UDP.write((char *)sd, 8);
        BLINKER_LOG("关闭主机");
        UDP.endPacket();
        oState = false;
    }
    BlinkerAliGenie.powerState(oState ? "on" : "off");
    BlinkerAliGenie.print();
}

void aligenieQuery(int32_t queryCode)
{
    BLINKER_LOG("AliGenie Query codes: ", queryCode);
    switch (queryCode)
    {
    case BLINKER_CMD_QUERY_ALL_NUMBER:
        BLINKER_LOG("AliGenie Query All");
        BlinkerAliGenie.powerState(oState ? "on" : "off");
        BlinkerAliGenie.print();
        break;
    case BLINKER_CMD_QUERY_POWERSTATE_NUMBER:
        BLINKER_LOG("AliGenie Query Power State");
        BlinkerAliGenie.powerState(oState ? "on" : "off");
        BlinkerAliGenie.print();
        break;
    default:
        BlinkerAliGenie.powerState(oState ? "on" : "off");
        BlinkerAliGenie.print();
        break;
    }
}

void dataRead(const String &data)
{
    BLINKER_LOG("Blinker readString: ", data);
    Blinker.vibrate();
    uint32_t BlinkerTime = millis();
    Blinker.print("millis", BlinkerTime);
}

void setup()
{
    Serial.begin(115200);
    BLINKER_DEBUG.stream(Serial);
    // BLINKER_DEBUG.debugAll();

    myservo.attach(0);  //servo.attach():设置舵机数据引脚
    myservo.write(90);  //servo.write():设置转动角度

    Button1.attach(button1_callback);
    Slider1.attach(slider1_callback);
    Blinker.attachHeartbeat(heartbeat);

    Blinker.begin(auth, ssid, pswd);
    Blinker.attachData(dataRead);

    BlinkerMIOT.attachPowerState(miotPowerState);
    BlinkerMIOT.attachQuery(miotQuery);

    BlinkerDuerOS.attachPowerState(duerPowerState);
    BlinkerDuerOS.attachQuery(duerQuery);

    BlinkerAliGenie.attachPowerState(aligeniePowerState);
    BlinkerAliGenie.attachQuery(aligenieQuery);
}

void loop()
{
    Blinker.run();
}
